package vip.xiaonuo.common.util;


import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import vip.xiaonuo.common.exception.CommonException;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.util.*;

/**
 * @author zjt
 * @description
 * @date 2024/9/18 下午6:32
 */
@Slf4j
public class CommonDateUtil {

    public static final String ISO_DATE = "yyyy-MM-dd";

    public static final String COMPACT_DATETIME_MILLIS = "yyMMddHHmmssSSS";

    public static final String YEAR_MONTH_DATE = "yyyyMMdd";

    public static final String COMPACT_DATE = "yyMMdd";

    public static final String ISO_DATETIME = "yyyy-MM-dd HH:mm:ss";

    public static final String COMPACT_YEAR_MONTH = "yyyyMM";

    public static final String TEXT_DATA = "yyyy年MM月dd日";

    private static final String SLASH_DATE = "yyyy/M/d";

    private static final String SLASH_DATETIME = "yyyy/M/d HH:mm:ss";

    private static final String CHINESE_DATE = "yyyy年M月d日";

    private static final String CHINESE_YEAR_MONTH = "yyyy年M月";

    public static final String NORM_DATETIME_MINUTE = "yyyy-M-d H:mm";

    private static final DateTimeFormatter OUTPUT_FORMATTER = DateTimeFormatter.ofPattern(ISO_DATE);
    private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd");
    private static final DateTimeFormatter ISO_DATETIME_FORMATTER = DateTimeFormatter.ofPattern(ISO_DATETIME);

    //获取当月
    public static String currentMonth() {
        Calendar calendar = Calendar.getInstance();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
        return sdf.format(calendar.getTime());
    }

    /**
     * 计算两个日期之间的天数差。
     * 如果输入日期为空，则返回 -1。
     *
     * @param endDate 结束日期字符串（格式为 yyyy-MM-dd）
     * @return 两个日期之间的天数差（绝对值）
     */
    public static int getDifferDay(String endDate) {
        if (StringUtils.isEmpty(endDate)) {
            return -1;
        }
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(ISO_DATE);
        // 解析给定的日期字符串为 LocalDate 对象
        LocalDate givenDate = LocalDate.parse(endDate, formatter);
        // 获取当前日期
        LocalDate today = LocalDate.now();
        // 计算天数差
        long daysBetween = ChronoUnit.DAYS.between(givenDate, today);
        // 返回天数差
        return Math.abs((int) daysBetween);
    }

    /**
     * 把毫秒数转成年月日时分秒
     */
    public static String formatMillisecondTime(long timestamp) {
        // 转换为北京时间（UTC+8）
        return Instant.ofEpochMilli(timestamp)
                .atZone(ZoneId.of("Asia/Shanghai"))
                .format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
    }

    /**
     * 获取当前时间的毫秒级时间戳字符串。
     * 格式为紧凑型日期时间毫秒格式：yyMMddHHmmssSSS。
     *
     * @return 当前时间的毫秒级时间戳字符串
     */
    public static String getMillisecondTime() {
        LocalDateTime now = LocalDateTime.now();
        // 定义时间格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(COMPACT_DATETIME_MILLIS);
        // 格式化时间
        return now.format(formatter);
    }

    /**
     * 获取当前日期的字符串表示。
     * 格式为 ISO 标准日期格式：yyyy-MM-dd。
     *
     * @return 当前日期的字符串表示
     */
    public static String getTodayStr() {
        LocalDateTime now = LocalDateTime.now();
        // 定义日期时间格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(ISO_DATE);
        // 格式化当前日期时间为字符串
        return now.format(formatter);
    }

    /**
     * 获取当前日期的文本格式字符串。
     * 格式为文本型日期格式：yyyy年MM月dd日。
     *
     * @return 当前日期的文本格式字符串
     */
    public static String getTodayStrText() {
        LocalDateTime now = LocalDateTime.now();
        // 定义日期时间格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(TEXT_DATA);
        // 格式化当前日期时间为字符串
        return now.format(formatter);
    }

    /**
     * 获取指定天数偏移量后的日期字符串。
     *
     * @param daysOffset 天数偏移量（正数表示几天后，负数表示几天前）
     * @return 偏移后的日期字符串（格式为 yyyy-MM-dd）
     */
    public static String getOffsetDateStr(int daysOffset) {
        // 获取当前时间
        LocalDateTime now = LocalDateTime.now();
        // 定义日期格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(ISO_DATE);
        // 根据传入的天数偏移量计算新日期
        LocalDateTime offsetDate = now.plusDays(daysOffset);
        // 将日期格式化为字符串并返回
        return offsetDate.format(formatter);
    }

    /**
     * 获取指定时间前或后的若干分钟的时间。
     * 如果输入时间字符串为空，则默认为当前时间。
     *
     * @param timeStr 指定的时间字符串（格式为 yyyy-MM-dd HH:mm:ss）
     * @param minutes 需要加减的分钟数（正数表示之后的时间，负数表示之前的时间）
     * @return 调整后的时间字符串（格式为 yyyy-MM-dd HH:mm:ss）
     */
    public static String getTimeBeforeOrAfterMinutes(String timeStr, int minutes) {
        if (StringUtils.isBlank(timeStr)) {
            timeStr = getCurrentTimeStr();
        }
        // 根据格式字符串创建 DateTimeFormatter 实例
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(ISO_DATETIME);
        // 将字符串解析为 LocalDateTime 对象
        LocalDateTime dateTime = LocalDateTime.parse(timeStr, formatter);
        // 计算指定时间前或后的若干分钟的时间
        LocalDateTime resultDateTime = dateTime.plusMinutes(minutes);
        // 格式化结果并返回
        return resultDateTime.format(formatter);
    }

    public static String getDateBeforeOrAfterDays(String dateStr, int days) {
        SimpleDateFormat sdf = new SimpleDateFormat(ISO_DATE);
        Date date = null;
        try {
            date = sdf.parse(dateStr);
        } catch (ParseException e) {
            log.error("{}:日期转换失败", dateStr, e);
            return getTodayStr();
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DATE, days);
        return sdf.format(calendar.getTime());
    }

    /**
     * 将 java.util.Date 对象格式化为日期字符串。
     * 格式为 ISO 标准日期格式：yyyy-MM-dd。
     *
     * @param date java.util.Date 对象
     * @return 格式化后的日期字符串
     */
    public static String dateToStr(Date date) {
        // 定义日期时间格式
        SimpleDateFormat formatter = new SimpleDateFormat(ISO_DATE);
        // 格式化当前日期时间为字符串
        return formatter.format(date);
    }

    /**
     * 将 java.util.Date 对象格式化为日期时间字符串。
     * 格式为 ISO 标准日期时间格式：yyyy-MM-dd HH:mm:ss。
     *
     * @param date java.util.Date 对象
     * @return 格式化后的日期时间字符串
     */
    public static String dateTimeToStr(Date date) {
        // 定义日期时间格式
        SimpleDateFormat formatter = new SimpleDateFormat(ISO_DATETIME);
        // 格式化当前日期时间为字符串
        return formatter.format(date);
    }


    /**
     * 将日期时间字符串转换为 java.util.Date 对象。
     * 字符串格式应为 ISO 标准日期时间格式：yyyy-MM-dd HH:mm:ss。
     *
     * @param dateStr 日期时间字符串
     * @return 转换后的Date对象
     * @throws ParseException 如果字符串格式不匹配
     */
    public static Date strToDateTime(String dateStr) {
        // 定义日期时间格式（与dateTimeToStr方法保持一致）
        SimpleDateFormat formatter = new SimpleDateFormat(ISO_DATETIME);
        // 解析字符串为Date对象
        try {
            return formatter.parse(dateStr);
        } catch (ParseException e) {
            log.info("{}:字符串转Date失败", dateStr, e);
            return new Date();
        }
    }


    /**
     * 将日期字符串解析为 java.util.Date 对象。
     * 输入日期字符串格式为 ISO 标准日期格式：yyyy-MM-dd。
     *
     * @param date 日期字符串
     * @return 解析后的 java.util.Date 对象
     */
    public static Date strToDate(String date) {
        SimpleDateFormat formatter = new SimpleDateFormat(ISO_DATE);
        try {
            return formatter.parse(date);
        } catch (ParseException e) {
            System.err.println("Error parsing date: " + e.getMessage());
            return null;
        }
    }

    /**
     * 获取当前日期的紧凑型日期字符串。
     * 格式为紧凑型日期格式：yyyyMMdd。
     *
     * @return 当前日期的紧凑型日期字符串
     */
    public static String getYearMonthDateStr() {
        LocalDateTime now = LocalDateTime.now();
        // 定义日期时间格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(YEAR_MONTH_DATE);
        // 格式化当前日期时间为字符串
        return now.format(formatter);
    }

    /**
     * 获取当前日期的紧凑型日期字符串。
     * 格式为紧凑型日期格式：yyMMdd。
     *
     * @return 当前日期的紧凑型日期字符串
     */
    public static String getTodayStrB() {
        LocalDateTime now = LocalDateTime.now();
        // 定义日期时间格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(COMPACT_DATE);
        // 格式化当前日期时间为字符串
        return now.format(formatter);
    }

    /**
     * 获取前一天的日期字符串。
     * 格式为 ISO 标准日期格式：yyyy-MM-dd。
     *
     * @return 前一天的日期字符串
     */
    public static String getPreviousDayStr() {
        LocalDateTime now = LocalDateTime.now();
        // 计算前一天的时间
        LocalDateTime previousDay = now.minusDays(1);
        // 定义日期时间格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(ISO_DATE);
        // 格式化前一天的时间为字符串
        return previousDay.format(formatter);
    }

    /**
     * 获取当前时间的字符串表示。
     * 格式为 ISO 标准日期时间格式：yyyy-MM-dd HH:mm:ss。
     *
     * @return 当前时间的字符串表示
     */
    public static String getCurrentTimeStr() {
        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(ISO_DATETIME);
        return now.format(formatter);
    }

    /**
     * 将不同格式的日期字符串转换为 yyyy-MM-dd 标准格式。
     *
     * @param dateStr 输入的日期字符串（支持多种格式）
     * @return 转换后的 yyyy-MM-dd 格式字符串
     * @throws CommonException 如果输入格式无法解析
     */
    public static String convertToDate(String dateStr) {
        // 检查输入是否为空或空白字符串
        if (StringUtils.isBlank(dateStr)) {
            return null;
        }
        try {
            // 处理标准日期格式：yyyy-MM-dd（如 2025-04-11）
            if (dateStr.matches("^\\d{4}-\\d{1,2}-\\d{1,2}$")) {
                LocalDate date = LocalDate.parse(dateStr, DateTimeFormatter.ISO_LOCAL_DATE);
                return date.format(OUTPUT_FORMATTER);
            }
            // 处理完整日期时间格式：yyyy-MM-dd HH:mm:ss（如 2025-04-11 09:19:30）
            else if (dateStr.matches("^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$")) {
                LocalDateTime dateTime = LocalDateTime.parse(dateStr, DateTimeFormatter.ofPattern(ISO_DATETIME));
                return dateTime.format(OUTPUT_FORMATTER);
            }
            // 处理带时分的不完整日期时间格式：yyyy-MM-dd HH:mm（如 2025-4-7 9:19）
            else if (dateStr.matches("^\\d{4}-\\d{1,2}-\\d{1,2} \\d{1,2}:\\d{2}$")) {
                LocalDateTime dateTime = LocalDateTime.parse(dateStr, DateTimeFormatter.ofPattern(NORM_DATETIME_MINUTE));
                return dateTime.format(OUTPUT_FORMATTER);
            }
            // 处理斜杠分隔的日期格式：yyyy/MM/dd（如 2025/04/11）
            else if (dateStr.matches("^\\d{4}/\\d{1,2}/\\d{1,2}$")) {
                LocalDate date = LocalDate.parse(dateStr, DateTimeFormatter.ofPattern(SLASH_DATE));
                return date.format(OUTPUT_FORMATTER);
            }
            // 处理斜杠分隔带时间的日期格式：yyyy/MM/dd HH:mm:ss（如 2025/04/08 19:59:47）
            else if (dateStr.matches("^\\d{4}/\\d{2}/\\d{2} \\d{2}:\\d{2}:\\d{2}$")) {
                LocalDateTime dateTime = LocalDateTime.parse(dateStr, DateTimeFormatter.ofPattern(SLASH_DATETIME));
//                LocalDateTime dateTime = LocalDateTime.parse(dateStr, DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss"));
                return dateTime.format(OUTPUT_FORMATTER);
            }
            // 处理中文日期格式：yyyy年MM月dd日（如 2025年4月11日）
            else if (dateStr.matches("^\\d{4}年\\d{1,2}月\\d{1,2}日$")) {
                LocalDate date = LocalDate.parse(dateStr, DateTimeFormatter.ofPattern(CHINESE_DATE));
                return date.format(DateTimeFormatter.ISO_DATE);
            }
            // 处理基本ISO日期格式：yyyyMMdd（如 20250411）
            else if (dateStr.matches("^\\d{8}$")) {
                LocalDate date = LocalDate.parse(dateStr, DateTimeFormatter.BASIC_ISO_DATE);
                return date.format(OUTPUT_FORMATTER);
            }
            // 处理英文月份简写格式：MMM d, yyyy（如 Apr 11, 2025）
            else if (dateStr.matches("^[A-Za-z]{3} \\d{1,2}, \\d{4}$")) {
                LocalDate date = LocalDate.parse(dateStr, DateTimeFormatter.ofPattern("MMM d, yyyy", Locale.ENGLISH));
                return date.format(OUTPUT_FORMATTER);
            }
            // 处理ISO日期时间格式（带时区）：yyyy-MM-ddTHH:mm:ssZ（如 2025-04-11T09:19:30Z）
            else if (dateStr.matches("^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$")) {
                ZonedDateTime zonedDateTime = ZonedDateTime.parse(dateStr, DateTimeFormatter.ISO_DATE_TIME);
                return zonedDateTime.format(OUTPUT_FORMATTER);
            }
            // 尝试使用默认解析器处理其他可能的ISO格式
            else {
                try {
                    LocalDate date = LocalDate.parse(dateStr);
                    return date.format(OUTPUT_FORMATTER);
                } catch (DateTimeParseException e) {
                    throw new CommonException("无法识别的日期格式：" + dateStr);
                }
            }
        } catch (DateTimeParseException e) {
            throw new CommonException("日期解析失败：" + e.getMessage());
        }
    }


    /**
     * 获取半小时前的时间字符串。
     * 格式为 ISO 标准日期时间格式：yyyy-MM-dd HH:mm:ss。
     *
     * @return 半小时前的时间字符串
     */
    public static String getHalfHourAgo() {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime halfHourAgo = now.minusMinutes(30);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(ISO_DATETIME);
        return halfHourAgo.format(formatter);
    }

    /**
     * 获取今天剩余时间（单位：秒）。
     *
     * @return 今天剩余的秒数
     */
    public static long getTodayDuration() {
        ZonedDateTime now = ZonedDateTime.now(ZoneId.systemDefault());
        LocalDateTime endOfDay = now.toLocalDate().atTime(LocalTime.MAX);
        ZonedDateTime endOfDayZoned = endOfDay.atZone(now.getZone());
        Duration duration = Duration.between(now, endOfDayZoned);
        return duration.getSeconds();
    }

    /**
     * 获取今天剩余时间（单位：秒）。
     *
     * @return 今天剩余的秒数
     */
    public static long getYearRemainingSeconds() {
        ZonedDateTime now = ZonedDateTime.now(ZoneId.systemDefault());
        ZonedDateTime endOfYear = now.with(TemporalAdjusters.lastDayOfYear())
                .with(LocalTime.MAX);
        return ChronoUnit.SECONDS.between(now, endOfYear);
    }

    /**
     * 获取当月第一天的日期字符串。
     * 格式为 ISO 标准日期格式：yyyy-MM-dd。
     *
     * @return 当月第一天的日期字符串
     */
    public static String getCurrentMonthFirstDay() {
        // 获取当前日期
        LocalDate today = LocalDate.now();
        // 获取当前月份的第一天
        LocalDate firstDayOfMonth = today.withDayOfMonth(1);
        return firstDayOfMonth.format(DateTimeFormatter.ofPattern(ISO_DATE));
    }

    /**
     * 获取当月最后一天的日期字符串。
     * 格式为 ISO 标准日期格式：yyyy-MM-dd。
     *
     * @return 当月第一天的日期字符串
     */
    public static String getCurrentMonthLastDay() {
        // 获取当前日期
        LocalDate today = LocalDate.now();
        // 获取当前月份的最后一天
        LocalDate lastDayOfMonth = today.with(TemporalAdjusters.lastDayOfMonth());
        return lastDayOfMonth.format(DateTimeFormatter.ofPattern(ISO_DATE));
    }

    /**
     * 获取指定月数后的月份的第一天的日期字符串。
     * 格式为 ISO 标准日期格式：yyyy-MM-dd。
     *
     * @param monthsToAdd 要添加的月数，必须为非负数
     * @return 日期字符串，格式为 yyyy-MM-dd
     * @throws IllegalArgumentException 如果入参为负数
     */
    public static String getFirstDayOfNextMonth(int monthsToAdd) {
        if (monthsToAdd < 0) {
            throw new IllegalArgumentException("入参不能为负数");
        }
        // 获取当前日期
        LocalDate currentDate = LocalDate.now();
        // 获取当前年月
        YearMonth currentYearMonth = YearMonth.from(currentDate);
        // 加上指定的月份数
        YearMonth nextYearMonth = currentYearMonth.plusMonths(monthsToAdd);
        // 获取该月的第一天
        LocalDate firstDay = nextYearMonth.atDay(1);
        // 将日期格式化为 yyyy-MM-dd 字符串
        return firstDay.format(DateTimeFormatter.ISO_DATE);
    }

    /**
     * 获取上个月的第一天的日期字符串。
     * 格式为 ISO 标准日期格式：yyyy-MM-dd。
     *
     * @return 上个月第一天的日期字符串
     */
    public static String getLastMonthFirstDay() {
        // 获取当前日期
        LocalDate today = LocalDate.now();
        // 获取上个月的第一天
        LocalDate firstDayOfLastMonth = today.minusMonths(1).withDayOfMonth(1);
        // 格式化日期为字符串
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(ISO_DATE);
        return firstDayOfLastMonth.format(formatter);
    }

    /**
     * 获取上个月的今天日期字符串。
     * 如果上个月没有对应的日期（例如，今天是 31 日，而上个月没有 31 日），则返回上个月的最后一天。
     * 格式为 ISO 标准日期格式：yyyy-MM-dd。
     *
     * @return 上个月的今天日期字符串
     */
    public static String getLastMonthToday() {
        LocalDate today = LocalDate.now();
        // 获取上个月的同一天
        LocalDate lastMonthToday = today.minusMonths(1).withDayOfMonth(today.getDayOfMonth());
        // 检查上个月是否有对应的日期
        if (lastMonthToday.getMonthValue() != today.minusMonths(1).getMonthValue()) {
            // 如果没有对应的日期，则获取上个月的最后一天
            lastMonthToday = today.minusMonths(1).withDayOfMonth(today.minusMonths(1).lengthOfMonth());
        }
        // 格式化日期为字符串
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(ISO_DATE);
        return lastMonthToday.format(formatter);
    }

    /**
     * 获取当前年月的字符串表示。
     * 格式为紧凑型年月格式：yyyyMM。
     *
     * @return 当前年月的字符串表示
     */
    public static String getCurrentMonth() {
        // 获取当前日期
        LocalDate today = LocalDate.now();
        // 获取当前月份的第一天
        LocalDate firstDayOfMonth = today.withDayOfMonth(1);
        return firstDayOfMonth.format(DateTimeFormatter.ofPattern(COMPACT_YEAR_MONTH));
    }

    /**
     * 获取上个月的年月字符串表示。
     * 格式为紧凑型年月格式：yyyyMM。
     *
     * @return 上个月的年月字符串表示
     */
    public static String getLastMonth() {
        // 获取当前日期
        LocalDate today = LocalDate.now();
        // 获取上个月的年月
        LocalDate firstDayOfLastMonth = today.minusMonths(1);
        return firstDayOfLastMonth.format(DateTimeFormatter.ofPattern(COMPACT_YEAR_MONTH));
    }

    /**
     * 将不同格式的日期字符串转换为 yyyyMM 格式（如 202502）
     *
     * @param dateStr 输入的日期字符串（支持多种格式）
     * @return 转换后的 yyyyMM 格式字符串
     * @throws CommonException 如果输入格式无法解析
     */
    public static String convertToYearMonth(String dateStr) {
        if (dateStr == null || dateStr.trim().isEmpty()) {
            throw new CommonException("输入日期字符串不能为空");
        }
        DateTimeFormatter outputFormat = DateTimeFormatter.ofPattern(COMPACT_YEAR_MONTH);
        try {
            // 1. 处理 "2025-2"、"2025-02-01"、"2025-02-01 11:11:11" 等格式
            if (dateStr.matches("^\\d{4}-\\d{1,2}$")) {
                LocalDate date = LocalDate.parse(dateStr + "-01", DateTimeFormatter.ofPattern("yyyy-M-d"));
                return date.format(outputFormat);
            } else if (dateStr.matches("^\\d{4}-\\d{2}-\\d{2}$")) {
                LocalDate date = LocalDate.parse(dateStr, DateTimeFormatter.ISO_LOCAL_DATE);
                return date.format(outputFormat);
            } else if (dateStr.matches("^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$")) {
                LocalDateTime dateTime = LocalDateTime.parse(dateStr, DateTimeFormatter.ofPattern(ISO_DATETIME));
                return dateTime.format(outputFormat);
            }
            // 2. 处理 "2025/2"、"2025/02/01"、"2025/02/01 11:11:11" 等斜杠格式
            else if (dateStr.matches("^\\d{4}/\\d{1,2}$")) {
                LocalDate date = LocalDate.parse(dateStr + "/01", DateTimeFormatter.ofPattern(SLASH_DATE));
                return date.format(outputFormat);
            } else if (dateStr.matches("^\\d{4}/\\d{2}/\\d{2}$")) {
                LocalDate date = LocalDate.parse(dateStr, DateTimeFormatter.ofPattern("yyyy/MM/dd"));
                return date.format(outputFormat);
            } else if (dateStr.matches("^\\d{4}/\\d{2}/\\d{2} \\d{2}:\\d{2}:\\d{2}$")) {
                LocalDateTime dateTime = LocalDateTime.parse(dateStr, DateTimeFormatter.ofPattern(
                        SLASH_DATETIME));
                return dateTime.format(outputFormat);
            }
            // 3. 处理 "202502"、"20250201"、"20250201111111" 等无分隔符格式
            else if (dateStr.matches("^\\d{6}$")) {
                // 已经是 yyyyMM 格式，直接返回
                return dateStr;
            } else if (dateStr.matches("^\\d{8}$")) {
                LocalDate date = LocalDate.parse(dateStr, DateTimeFormatter.BASIC_ISO_DATE);
                return date.format(outputFormat);
            } else if (dateStr.matches("^\\d{14}$")) {
                LocalDateTime dateTime = LocalDateTime.parse(dateStr, DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
                return dateTime.format(outputFormat);
            }
            // 4. 处理 "2025年2月"、"2025年02月01日" 等中文格式
            else if (dateStr.matches("^\\d{4}年\\d{1,2}月$")) {
                LocalDate date = LocalDate.parse(dateStr + "01日", DateTimeFormatter.ofPattern(CHINESE_YEAR_MONTH));
                return date.format(outputFormat);
            } else if (dateStr.matches("^\\d{4}年\\d{2}月\\d{2}日$")) {
                LocalDate date = LocalDate.parse(dateStr, DateTimeFormatter.ofPattern(CHINESE_DATE));
                return date.format(outputFormat);
            }
            // 5. 处理 ISO 8601 带时区格式，如 "2025-02-01T11:11:11Z"
            else if (dateStr.matches("^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$")) {
                ZonedDateTime zonedDateTime = ZonedDateTime.parse(dateStr, DateTimeFormatter.ISO_DATE_TIME);
                return zonedDateTime.format(outputFormat);
            }
            // 6. 其他格式尝试自动解析（宽松模式）
            else {
                try {
                    // 尝试解析为 LocalDate
                    LocalDate date = LocalDate.parse(dateStr);
                    return date.format(outputFormat);
                } catch (DateTimeParseException e1) {
                    try {
                        // 尝试解析为 LocalDateTime
                        LocalDateTime dateTime = LocalDateTime.parse(dateStr);
                        return dateTime.format(outputFormat);
                    } catch (DateTimeParseException e2) {
                        throw new CommonException("无法识别的日期格式：" + dateStr);
                    }
                }
            }
        } catch (DateTimeParseException e) {
            throw new CommonException("日期解析失败：" + e.getMessage());
        }
    }

    /**
     * 判断指定日期是否是当前日期加上指定天数后的日期
     *
     * @param date 要判断的日期
     * @param days 指定天数（正数表示未来，负数表示过去）
     * @return 如果指定日期是当前日期加上指定天数后的日期，返回 true；否则返回 false
     */
    public static boolean isDateWithSpecifiedDays(Date date, int days) {
        if (date == null) {
            throw new CommonException("Date cannot be null");
        }
        // 将 Date 转换为 LocalDate
        LocalDate targetDate = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        // 获取当前日期
        LocalDate today = LocalDate.now();
        // 计算当前日期加上指定天数后的日期
        LocalDate calculatedDate = today.plusDays(days);
        // 判断目标日期是否等于计算后的日期
        return targetDate.equals(calculatedDate);
    }

    /**
     * 判断指定日期是否大于或小于当前日期加上指定天数后的日期。
     * 正数表示判断是否大于，负数表示判断是否小于。
     *
     * @param date 要判断的日期
     * @param days 指定天数（正数表示大于，负数表示小于）
     * @return 如果满足条件返回 true，否则返回 false
     */
    public static boolean compareDateWithSpecifiedDays(Date date, int days) {
        if (date == null) {
            throw new CommonException("Date cannot be null");
        }
        // 将 Date 转换为 LocalDate
        LocalDate targetDate = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        // 获取当前日期
        LocalDate today = LocalDate.now();
        // 计算当前日期加上指定天数后的日期
        LocalDate calculatedDate = today.plusDays(days);
        // 判断逻辑：正数判断是否大于，负数判断是否小于
        if (days > 0) {
            return targetDate.isAfter(calculatedDate); // 判断是否大于
        } else if (days < 0) {
            return targetDate.isBefore(calculatedDate); // 判断是否小于
        } else {
            throw new CommonException("Days cannot be zero");
        }
    }

    public static boolean isAfterMinutes(String timeStr, long minutes) {
        try {
            // 解析输入的时间字符串
            LocalDateTime inputTime = LocalDateTime.parse(timeStr, DateTimeFormatter.ofPattern(ISO_DATETIME));
            // 获取当前时间
            LocalDateTime now = LocalDateTime.now();

            // 计算目标时间（当前时间加上或减去分钟数）
            LocalDateTime targetTime;
            if (minutes >= 0) {
                // 正数：当前时间加上分钟数
                targetTime = now.plusMinutes(minutes);
                // 判断输入时间是否晚于目标时间
                return inputTime.isAfter(targetTime);
            } else {
                // 负数：当前时间减去分钟数
                targetTime = now.minusMinutes(Math.abs(minutes));
                // 判断输入时间是否早于目标时间
                return inputTime.isBefore(targetTime);
            }
        } catch (DateTimeParseException e) {
            throw new CommonException("时间格式无效，应为 yyyy-MM-dd HH:mm:ss", e);
        }
    }

    /**
     * 将秒级时间戳转换为指定格式的日期字符串
     *
     * @param timestamp 秒级时间戳
     * @return 格式化后的日期字符串
     */
    public static String formatTimestamp(long timestamp) {
        // 将秒级时间戳转换为毫秒级
        long milliseconds = timestamp * 1000L;
        // 创建 Date 对象
        Date date = new Date(milliseconds);
        // 创建 SimpleDateFormat 对象并设置格式
        SimpleDateFormat sdf = new SimpleDateFormat(ISO_DATETIME);
        // 格式化日期并返回
        return sdf.format(date);
    }

    public static boolean isBeforeLastMonth(String dateStr) {
        LocalDate inputDate = LocalDate.parse(dateStr, FORMATTER);
        LocalDate lastMonth = LocalDate.now().minusMonths(1);
        return inputDate.isBefore(lastMonth.withDayOfMonth(1));
    }

    public static boolean isBeforeTodayMidnight(String dateString) {
        // 定义日期格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(ISO_DATETIME);
        // 解析输入的日期字符串
        LocalDateTime inputDate = LocalDateTime.parse(dateString, formatter);
        // 获取当天的 0 点
        LocalDateTime todayMidnight = LocalDateTime.of(LocalDate.now(), LocalTime.MIN);
        // 比较输入日期和当天的 0 点
        return inputDate.isBefore(todayMidnight);
    }

    public static List<String> getDatesBetween(String startDate, String endDate) {
        List<String> dates = new ArrayList<>();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(ISO_DATE);
        LocalDate start = LocalDate.parse(startDate, formatter);
        LocalDate end = LocalDate.parse(endDate, formatter);
        while (!start.isAfter(end)) {
            dates.add(start.format(formatter));
            start = start.plusDays(1);
        }
        return dates;
    }

    public static int toUint32Timestamp(String dateTimeStr) throws IllegalArgumentException {
        long timestamp = LocalDateTime.parse(dateTimeStr, ISO_DATETIME_FORMATTER)
                .atZone(ZoneId.systemDefault())
                .toInstant()
                .toEpochMilli() / 1000L;
        if (timestamp < 0 || timestamp > 4294967295L) {
            throw new IllegalArgumentException("Timestamp out of uint32 range");
        }
        return (int) timestamp;
    }

    // uint32时间戳字符串转日期字符串
    public static String uint32StrToDate(String timestampStr) {
        long timestamp = Long.parseLong(timestampStr);
        if (timestamp < 0 || timestamp > 4294967295L) {
            throw new IllegalArgumentException("Timestamp out of uint32 range");
        }
        return LocalDateTime.ofEpochSecond(timestamp, 0,
                        ZoneId.systemDefault().getRules().getOffset(Instant.now()))
                .format(ISO_DATETIME_FORMATTER);
    }

    /**
     * 获取从开始日期到当前日期的所有日期列表
     *
     * @param startDateStr 开始日期字符串，格式为yyyyMMdd
     * @return 日期字符串列表，格式为yyyyMMdd
     */
    public static List<String> getDateRangeToToday(String startDateStr) {
        List<String> dateList = new ArrayList<>();
        try {
            LocalDate startDate = LocalDate.parse(startDateStr, DateTimeFormatter.ofPattern(YEAR_MONTH_DATE));
            LocalDate endDate = LocalDate.now();
            while (!startDate.isAfter(endDate)) {
                dateList.add(startDate.format(DateTimeFormatter.ofPattern(YEAR_MONTH_DATE)));
                startDate = startDate.plusDays(1);
            }
        } catch (Exception e) {
            throw new IllegalArgumentException("日期格式错误，请输入yyyyMMdd格式的日期");
        }
        return dateList;
    }
}